home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2000 February / Macworld (2000-02).dmg / Updaters / WhiteCap 3.2.2.sea / WhiteCap 3.2.2 / WhiteCap Source / WhiteCapWorld.cpp < prev    next >
C/C++ Source or Header  |  1999-10-27  |  17KB  |  611 lines

  1. #include "WhiteCapWorld.h"
  2.  
  3. // Praise Jesus! I can't keep quiet...Ye-haw!
  4.  
  5. #include "Sample.h"
  6. #include "CEgIFile.h"
  7. #include "ArgList.h"
  8. #include "R3Matrix.h"
  9.  
  10. #if EG_MAC
  11. #include <Dialogs.h>
  12.  
  13.  
  14. #endif
  15.  
  16. #if EG_WIN
  17. #include "RectUtils.h"
  18. #endif
  19.  
  20. #include "PixPort.h"
  21. #include "EgOSUtils.h"
  22. #include "CEgFileSpec.h"
  23.  
  24.  
  25. WhiteCapWorld::WhiteCapWorld()  {
  26.     
  27.     mSamples        = NULL;
  28.     mRecentSample    = NULL;
  29.     mWave            = NULL;
  30.     mTransitionTime    = -1;
  31.     mPi                = 3.1415926535897;
  32.     mCurBackClr        = -1;        // This will cause an update to mCurBackClr in Render()
  33.     mNumSampleBins    = NUM_SAMPLE_BINS;
  34.     
  35.     mDict.AddVar( "S", &mS );
  36.     mDict.AddVar( "T", &mT );
  37.     mDict.AddVar( "ST", &mST );
  38.     mDict.AddVar( "DT", &mDT );
  39.     mDict.AddVar( "PI", &mPi );
  40.     mDict.AddVar( "NUM_SAMPLE_BINS", &mNumSampleBins );        // Let user read num sample bins if they want
  41.     mDict.AddVar( "BASS1", &mBass1 );
  42.     mDict.AddVar( "BASS2", &mBass2 );
  43.     mDict.AddVar( "BASS3", &mBass3 );
  44.     mDict.AddFcn( "MAG", &mMagPtr, NUM_SAMPLE_BINS );
  45.  
  46.  
  47.     SetRect( &mPaneRect, 5000, 5000, -5000, -5000 );
  48. }
  49.  
  50.  
  51.  
  52. WhiteCapWorld::~WhiteCapWorld() {
  53.     Sample *sample;
  54.     
  55.     // Move all the sample to the mFreeList
  56.     ExpireSamples();
  57.     
  58.     // Delete all the sample from the free list
  59.     while ( mFreeList.FetchLast( &sample ) ) {
  60.         delete sample;
  61.         mFreeList.RemoveLast();
  62.     }
  63. }
  64.  
  65.  
  66.  
  67.  
  68.  
  69. #define __FACTORY    "\
  70. Resn=10,\
  71. Durn=\".8\",\
  72. CamX=\"59*cos(t/5)\",\
  73. CamY=\"50*sin(t/6)\",\
  74. CamZ=\"25 + 10*cos(t/11)\",\
  75. CmLX=\"40\",CmLY=\"0\",CmLZ=\"0\",\
  76. CUpX=\"0\",CUpY=\"0\",CUpZ=\"1\",\
  77. R=\"0\",G=\"1-dt\",B=\"0\",\
  78. LvlR=\"1\",LvlG=\"0\",LvlB=\"0\",\
  79. widt=320,heig=300,\
  80. ConL=1,ConB=1,\
  81. Fall=\"0.035\",\
  82. X=\"100*dt\",Y=\"130*s-65\",Z=\"20*abs( mag( s ) )\",\
  83. Scal=\"600\",\
  84. ScSz=1,\
  85. Vers=30,\
  86. Pers=\"350\""
  87.  
  88.  
  89.  
  90.  
  91.  
  92. void WhiteCapWorld::Init( const CEgFileSpec* inConfig, long inCurTime, long inTransitionTime ) {
  93.     CEgIFile file;
  94.     int ok, vers;
  95.     UtilStr        str, configText, num;
  96.     ArgList        args;
  97.     
  98.     file.open( inConfig );
  99.     args.SetArgs( &file );
  100.     ok = file.noErr();
  101.     if ( ok ) {
  102.         vers = args.GetArg( 'Vers' );
  103.         ok = vers == 30;
  104.     }
  105.  
  106.     // If something went wrong or we have an earlier version, default to the factory config    
  107.     if ( ! ok ) {
  108.         args.Clear();
  109.         args.SetArgs( __FACTORY );
  110.     }
  111.         
  112.     mTransitionTime = inTransitionTime;
  113.     mTransitionEnd = inCurTime + inTransitionTime;
  114.  
  115.     // If first time load, don't do any transition
  116.     if ( mWave == NULL ) {
  117.         mWave = &mWave1;
  118.         mNextWave = &mWave2;
  119.         mWave -> Assign( args, mDict );
  120.         mTransitionTime = -1;  
  121.         inConfig -> GetFileName( mWave -> mTitle );  }
  122.     else {
  123.         mNextWave -> Assign( args, mDict );
  124.         mWave -> SetupTransition( mNextWave, &mTransitionT, NULL );
  125.         inConfig -> GetFileName( mNextWave -> mTitle );
  126.     }
  127.     
  128. }
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135. void WhiteCapWorld::SetPaneRect( const Rect& inRect ) {
  136.     int width = inRect.right - inRect.left;
  137.     int heigt = inRect.bottom - inRect.top;
  138.     
  139.     mPaneRect = inRect;
  140.     
  141.     // Besure we erase the new rect are next time
  142.     mRenderedRect = mPaneRect;
  143.     
  144.     // Invaliadate this rect till later...
  145.     ::SetRect( &mTitleRect, 0, 0, 0, 0 );
  146.     
  147.     // If the scale changes with window size
  148.     mWave -> SetScaleToFit( width, heigt );
  149.     mNextWave -> SetScaleToFit( width, heigt );
  150. }
  151.  
  152.  
  153.  
  154.  
  155.  
  156.  
  157.  
  158.  
  159. #define __Chk( xx, yy ) x = xx; y = yy;                        \
  160.                         if ( x >= mRenderedRect.right )        \
  161.                             mRenderedRect.right = x+1;        \
  162.                         if ( x <= mRenderedRect.left )        \
  163.                             mRenderedRect.left = x-1;        \
  164.                         if ( y >= mRenderedRect.bottom )    \
  165.                             mRenderedRect.bottom = y+1;        \
  166.                         if ( y <= mRenderedRect.top )        \
  167.                             mRenderedRect.top = y-1;    
  168.  
  169.  
  170. #define _evalClr( var, clr )    { clrTemp = 65535.0 * mWave -> clr.Evaluate();  if ( clrTemp < 0 ) var = 0; else if ( clrTemp <= 0xFFFF ) var = clrTemp; else var = 0xFFFF;        }
  171.     
  172.  
  173. // Pre: Render() was called before this
  174. void WhiteCapWorld::DrawConfigName( void* inPort ) {
  175.     RGBColor clr;
  176.     float w;
  177.     unsigned char* str;
  178.         
  179.     // Save the current mac port.  Even if Win9X/NT is crap, it's APIs/Interfaces are pretty decent, namely the GDI stuff.
  180.     // But sure, then again, if an OS designed for 1984ish cpus can compete w/ a 'modern' OS, i'd be damned
  181.     // ashamed if i was on the Win implementation team...  
  182.     #if EG_MAC
  183.      GrafPtr    savePort;
  184.     ::GetPort( &savePort );
  185.     ::SetPort( (GrafPtr) inPort );                
  186.     ::TextFont( 20 );
  187.     ::TextSize( 12 );
  188.     #endif
  189.     
  190.     #if EG_WIN
  191.     HDC hdc = (HDC) inPort;
  192.     #endif
  193.     
  194.     mTitleRect.left = mPaneRect.left;
  195.     mTitleRect.bottom = mPaneRect.bottom;
  196.     mTitleRect.top = mPaneRect.bottom - 20;
  197.     
  198.     if ( mTransitionTime > 0 ) {
  199.  
  200.         if ( mTransitionT > .5 ) {
  201.             w = 2 * mTransitionT - 1;
  202.             str = mWave -> mTitle.getPasStr(); }
  203.         else {
  204.             w = 1 - 2 * mTransitionT;
  205.             str = mNextWave -> mTitle.getPasStr(); 
  206.         }
  207.             
  208.         clr.red   = mCurBackClrRGB.red        + w * ( mTextColor.red - mCurBackClrRGB.red );
  209.         clr.green = mCurBackClrRGB.green    + w * ( mTextColor.green - mCurBackClrRGB.green );
  210.         clr.blue  = mCurBackClrRGB.blue        + w * ( mTextColor.blue - mCurBackClrRGB.blue );
  211.         
  212.         #if EG_MAC
  213.         ::RGBForeColor( &clr );
  214.         ::MoveTo( mTitleRect.left + 4, mTitleRect.bottom - 4 );
  215.         ::DrawString( str );
  216.         #else
  217.         ::SetTextColor( hdc, __winRGB( clr.red, clr.green, clr.blue ) );
  218.         ::SetBkMode( hdc, TRANSPARENT );
  219.         ::TextOut( hdc, mTitleRect.left + 4, mTitleRect.top, (char*) &str[ 1 ], str[ 0 ] );
  220.         #endif
  221.     }
  222.     else {
  223.         #if EG_MAC
  224.         ::RGBForeColor( &mTextColor );
  225.         ::MoveTo( mTitleRect.left + 4, mTitleRect.bottom - 4 );
  226.         ::DrawString( mWave -> mTitle.getPasStr() );
  227.         #else
  228.         ::SetTextColor( hdc, __winRGB( mTextColor.red, mTextColor.green, mTextColor.blue ) );
  229.         ::SetBkMode( hdc, TRANSPARENT );
  230.         ::TextOut( hdc, mTitleRect.left + 4, mTitleRect.top, mWave -> mTitle.getCStr(), mWave -> mTitle.length() );
  231.         #endif
  232.     }
  233.     
  234.     #if EG_MAC
  235.     // Don't screw up future calls to copybits. Wtf--someone tell my my copyBits() freaks out when
  236.     // the fore color isn't black
  237.     clr.red = clr.green = clr.blue = 0;
  238.     ::RGBForeColor( &clr );
  239.     Point pt;
  240.     ::GetPen( &pt );
  241.     mTitleRect.right = pt.h;
  242.     
  243.     // Restore the prev mac port
  244.     ::SetPort( savePort );
  245.     #endif
  246.     
  247.     #if EG_WIN
  248.     mTitleRect.right = 250; //!!!  ##*
  249.     #endif
  250.  
  251. }
  252.  
  253.  
  254. #define __applySampleToGlobals( s )        mMagPtr = s -> mSample;                                                                                \
  255.                                         mST = .001 * ( (float) s -> mSampleTime );                                                                        \
  256.                                         mDT = ( (float) ( mLastSampleTime - s -> mSampleTime ) ) / ( (float) mWave -> mSampleDuration );    \
  257.                                         mBass1 = s -> mBass[ 0 ];                                                                            \
  258.                                         mBass2 = s -> mBass[ 1 ];                                                                            \
  259.                                         mBass3 = s -> mBass[ 2 ];
  260.  
  261.  
  262. //#include <Sound.h>
  263.  
  264. void WhiteCapWorld::Render( long inCurTime, PixPort& inPort, Rect& outDirtyRect ) {
  265.     V3 pt;
  266.     long x, y, curBlurNum, p_x, p_y, i, clrTemp;
  267.     short xorg    = ( mPaneRect.right + mPaneRect.left ) / 2;
  268.     short yorg    = ( mPaneRect.bottom + mPaneRect.top ) / 2;
  269.     R3Matrix T;
  270.     float stepSize, f_x, f_y, f_z;
  271.     Sample* sample;
  272.     long borderXtra;
  273.     RGBColor            curClr;
  274.     long                curWidth, prevWidth;
  275.     bool                transition;
  276.     static ScrnPt        sPt[ NUM_SAMPLE_BINS ];
  277.  
  278.     // Don't draw outside this world's pane
  279.     inPort.SetClipRect( &mPaneRect );
  280.  
  281.     // Calculate the position, direction, and rotation angle of the camera
  282.     mT = ((float) inCurTime ) / 1000.0;
  283.         
  284.     transition = mTransitionTime > 0;
  285.     if ( transition ) {
  286.         f_x = (float) ( mTransitionEnd - inCurTime ) / ( (float) mTransitionTime );
  287.         if ( f_x < 0 )
  288.             f_x = 0;
  289.         mTransitionT = pow( f_x, TRANSITION_ALPHA );
  290.         mWave -> SetupFrame( mNextWave, mTransitionT );
  291.     }
  292.     
  293.     // Before we eval all the "B" exprs, it's possiblle they use the mag() fcn--in B vars,
  294.     // it references the most recent sample.  Warning, if there's no samples available, any B
  295.     // vars that call mag() will get junk. 
  296.     if ( mSamples ) {
  297.         __applySampleToGlobals( mSamples ) }
  298.     else {
  299.         mMagPtr = (float*) sPt; 
  300.         mBass1 = 0;
  301.         mBass2 = 0;
  302.         mBass3 = 0;
  303.     }
  304.  
  305.     // Eval all the "B" exprs        
  306.     mWave -> mB_Var.Evaluate();
  307.     if ( transition )
  308.         mNextWave -> mB_Var.Evaluate();
  309.     
  310.     // Evaluate the current background color
  311.     _evalClr( mCurBackClrRGB.red, mBackR )        
  312.     _evalClr( mCurBackClrRGB.green, mBackG )    
  313.     _evalClr( mCurBackClrRGB.blue, mBackB )
  314.     clrTemp = inPort.SetBackColor( mCurBackClrRGB );
  315.     if ( clrTemp != mCurBackClr ) {
  316.         mCurBackClr = clrTemp;
  317.         mRenderedRect = mPaneRect; 
  318.     }
  319.         
  320.     // The Camera pos
  321.     mCamera.mPos.mX = mWave -> mCamX.Evaluate();
  322.     mCamera.mPos.mY = mWave -> mCamY.Evaluate();
  323.     mCamera.mPos.mZ = mWave -> mCamZ.Evaluate();
  324.     
  325.     // The Camera look direction
  326.     mCamera.mDir.mX = mWave -> mCamLX.Evaluate();
  327.     mCamera.mDir.mY = mWave -> mCamLY.Evaluate();
  328.     mCamera.mDir.mZ = mWave -> mCamLZ.Evaluate();
  329.     mCamera.mDir.subtract( mCamera.mPos );
  330.     
  331.     // The Camera "up" direction
  332.     mCamera.mUpDir.mX = mWave -> mCamUpX.Evaluate();
  333.     mCamera.mUpDir.mY = mWave -> mCamUpY.Evaluate();
  334.     mCamera.mUpDir.mZ = mWave -> mCamUpZ.Evaluate();
  335.     mCamera.mXYScale = mWave -> mXYScale;
  336.  
  337.     // Calc the main transformation matrix, T
  338.     mCamera.CalcTransMatrix( T );
  339.     
  340.     // Erase the area that has stuff drawn on it
  341.     outDirtyRect = mRenderedRect;
  342.     inPort.EraseRect( &mRenderedRect );
  343.     mRenderedRect.top = 5000;        mRenderedRect.left = 5000;
  344.     mRenderedRect.bottom = -5000;    mRenderedRect.right = -5000;
  345.     
  346.     /*
  347.     // Line diagnostic
  348.     for ( float ang = 0; ang < 2*PI; ang += .3 ) {
  349.         x = xorg + 50 * cos( ang + .05 * mT );
  350.         y = yorg - 50 * sin( ang + .05 * mT );
  351.         p_x = xorg + 150 * cos( ang + .05 * mT );
  352.         p_y = yorg - 150 * sin( ang + .05 * mT );
  353.         inPort.SetLineWidth( ang * 2 );
  354.         inPort.Line( x, y, p_x, p_y, 0x000A0A0A );
  355.         inPort.SetLineWidth( 1 );
  356.         inPort.Line( x, y, p_x, p_y, 0x000A000A );
  357.     }
  358.     outDirtyRect.left = xorg - 160;
  359.     outDirtyRect.right = xorg + 160;
  360.     outDirtyRect.top = yorg - 160;
  361.     outDirtyRect.bottom = yorg + 160;
  362.     mRenderedRect = outDirtyRect; 
  363.     return; */
  364.  
  365.  
  366.     // Draw each sample to the screen, starting from the oldest sample
  367.     curBlurNum = mWave -> mNumBlurs;
  368.     
  369.     // This gets bigger when the linewidth gets bigger
  370.     borderXtra = 0;
  371.  
  372.     // Make sure t will never be > 1.0
  373.     discardExpiredRows( inCurTime );
  374.         
  375.     // Cache stuff that gets looked up often
  376.     bool x_depS, y_depS, z_depS, r_depS, g_depS, b_depS;
  377.     x_depS = mWave -> mX_Dep_S;        
  378.     y_depS = mWave -> mY_Dep_S;
  379.     z_depS = mWave -> mZ_Dep_S;
  380.     r_depS = mWave -> mR_Dep_S;        
  381.     g_depS = mWave -> mG_Dep_S;
  382.     b_depS = mWave -> mB_Dep_S;    
  383.     
  384.     
  385.     // This is how many pieces we chop up s's interval from 0 to 1
  386.     stepSize = 1.0 / ( (float) ( mWave -> mNum_S_Steps ) );
  387.  
  388.         
  389.     for ( sample = mSamples; sample; sample = sample -> mNext ) {
  390.         
  391.         // Link mWave.mDict1 to the sample's wave data
  392.         // Assign the delta-time index (in secs) for this sample
  393.         __applySampleToGlobals( sample )
  394.         
  395.         // Evaluate all the "C" expressions
  396.         mWave -> mC_Var.Evaluate();
  397.         if ( transition )
  398.             mNextWave -> mC_Var.Evaluate();
  399.  
  400.         // Calc how wide this sample's linewidth is (round up if > .5)
  401.         prevWidth = curWidth;
  402.         curWidth = ( mWave -> mLineWidth.Evaluate() + 0.5 );
  403.         if ( curWidth > borderXtra )
  404.             borderXtra = curWidth;
  405.         inPort.SetLineWidth( curWidth );
  406.             
  407.         // Evaluate vars that are indep of S (or D)
  408.         if ( ! x_depS )    f_x = mWave -> mX.Evaluate() - mCamera.mPos.mX;
  409.         if ( ! y_depS )    f_y = mWave -> mY.Evaluate() - mCamera.mPos.mY;
  410.         if ( ! z_depS )    f_z = mWave -> mZ.Evaluate() - mCamera.mPos.mZ;
  411.         if ( ! r_depS )    _evalClr( curClr.red, mR )
  412.         if ( ! g_depS )    _evalClr( curClr.green, mG )
  413.         if ( ! b_depS )    _evalClr( curClr.blue, mB )
  414.         
  415.         // Draw the old samples to the new ones
  416.         for ( mS = 0, i = 0; i < mWave -> mNum_S_Steps; i++, mS += stepSize ) {
  417.             
  418.             // Evaluate all the "D" expressions
  419.             mWave -> mD_Var.Evaluate();
  420.             if ( transition )
  421.                 mNextWave -> mD_Var.Evaluate();
  422.  
  423.             // Only evaluate expressions that are dependent on S
  424.             pt.mX = ( x_depS ) ? mWave -> mX.Evaluate() - mCamera.mPos.mX : f_x;
  425.             pt.mY = ( y_depS ) ? mWave -> mY.Evaluate() - mCamera.mPos.mY : f_y;
  426.             pt.mZ = ( z_depS ) ? mWave -> mZ.Evaluate() - mCamera.mPos.mZ : f_z;
  427.             pt.transform( T, mWave -> mPerspectiveInt );
  428.             p_x = xorg + pt.mX;
  429.             p_y = yorg - pt.mY;
  430.                 
  431.             // Calc the screen pt and update out bounds rectangle
  432.             __Chk( p_x, p_y )
  433.     
  434.             // Calculate the color for this point
  435.             if ( r_depS )    _evalClr( curClr.red, mR )
  436.             if ( g_depS )    _evalClr( curClr.green, mG )
  437.             if ( b_depS )    _evalClr( curClr.blue, mB )
  438.                         
  439.             // Are we supposed to connect to the prev sample?  Also catch when we're drawin the first sample
  440.             if ( mWave -> mConnectSamples ) {
  441.                 if ( sample != mSamples ) {
  442.                     if ( sample -> mNext )
  443.                         inPort.Line( sPt[ i ].x, sPt[ i ].y, p_x, p_y, sPt[ i ].color, curClr );
  444.                     else {
  445.                         inPort.SetLineWidth( prevWidth );
  446.                         inPort.Line( sPt[ i ].x, sPt[ i ].y, p_x, p_y, sPt[ i ].color, curClr );
  447.                         inPort.SetLineWidth( curWidth );
  448.                     }
  449.                 }
  450.             }
  451.             
  452.             // Record key scrn info for current sample
  453.             sPt[ i ].x = p_x;
  454.             sPt[ i ].y = p_y;
  455.             
  456.             // Evaluate the level color (if it was given)
  457.             if ( sample -> mNext )
  458.                 sPt[ i ].color = curClr;
  459.             else {
  460.                 _evalClr( sPt[ i ].color.red, mLvlR )
  461.                 _evalClr( sPt[ i ].color.green, mLvlG )
  462.                 _evalClr( sPt[ i ].color.blue, mLvlB )
  463.             }
  464.  
  465.             // If we're connecting bins...
  466.             if ( mWave -> mConnectBins && i > 0 )
  467.                 inPort.Line( p_x, p_y, sPt[ i - 1 ].x, sPt[ i - 1 ].y, sPt[ i ].color, sPt[ i - 1 ].color );
  468.         
  469.             // If we're just drawing dots...    (we can skip drawing dots if samples are already connected)        
  470.             else if ( ! mWave -> mConnectSamples || ! sample -> mNext )
  471.                 inPort.Line( p_x, p_y, p_x, p_y, sPt[ i ].color, sPt[ i ].color );
  472.         }
  473.         
  474.         // Connect bin 0 and bin N is user wants it
  475.         if ( mWave -> mConnectFirstLast ) {
  476.             curClr = sPt[ mWave -> mNum_S_Steps - 1 ].color;
  477.             inPort.Line( p_x, p_y, sPt[ 0 ].x, sPt[ 0 ].y, curClr, curClr );
  478.         }
  479.         
  480.         // Do the blur if the number of blurs is valid
  481.         if ( mWave -> mNumBlurs > 0 ) {
  482.             float t_scale = 1000.0 * mDT / mWave -> mSampleDuration;
  483.             if ( t_scale <= ( (float) curBlurNum - 1.0) / mWave -> mNumBlurs ) {
  484.                 ::InsetRect( &mRenderedRect, - borderXtra - 3, - borderXtra - 3 );
  485.                 inPort.GaussBlur( mWave -> mBlurVal, mRenderedRect, NULL );
  486.                 curBlurNum--;
  487.             }    
  488.         }
  489.     }
  490.     
  491.     // We'll let the text color be the color of the s == 1 side of the level
  492.     if ( mSamples )
  493.         mTextColor = sPt[ 0 ].color;
  494.     else {
  495.         // cosmetic prob: when we don't have any samples, we don't have a clr for the text.
  496.         // What do we do?  for now, we'll just use the current back color
  497.         mTextColor = mCurBackClrRGB;
  498.     }
  499.  
  500.     // If we've just finished a transition, end it
  501.     if ( transition && inCurTime > mTransitionEnd ) {
  502.         WC_WaveShape* temp = mWave;
  503.         mWave = mNextWave;
  504.         mNextWave = temp;
  505.         mTransitionTime = -1;
  506.         mRenderedRect = mPaneRect;        // Refresh everthing
  507.     }
  508.     
  509.     // Things like line widths > 1 may have drawn a little outside our bounds rect
  510.     ::InsetRect( &mRenderedRect, -borderXtra - 1, -borderXtra - 1 );
  511.     
  512.     // The area we have to refresh either has new bits or old bits
  513.     ::UnionRect( &mRenderedRect, &outDirtyRect, &outDirtyRect );
  514.     
  515.     // Limit the refresh rect to our pane
  516.     ::SectRect( &mPaneRect, &outDirtyRect, &outDirtyRect );
  517. }
  518.  
  519.  
  520.  
  521.  
  522.  
  523.  
  524. void WhiteCapWorld::RefreshRect( const Rect& inRect ) {
  525.     Rect r;
  526.     
  527.     // Clip the rect to this pane
  528.     ::SectRect( &mPaneRect, &inRect, &r );
  529.  
  530.     
  531.     // Make sure we erase that part of the window next time
  532.     ::UnionRect( &mRenderedRect, &r, &mRenderedRect );
  533. }
  534.  
  535.  
  536.  
  537.  
  538.  
  539.  
  540. void WhiteCapWorld::RecordSample( long inCurTime, const float inSpectrum[] ) {
  541.     Sample* sample;
  542.             
  543.     // Store the newest sample, don't store anything if its less than our time resolution
  544.     if ( inCurTime - mLastSampleTime >= mWave -> mSampleDelay || mSamples == NULL ) {
  545.  
  546.         // Get a free sample structure
  547.         if ( mFreeList.FetchLast( &sample ) ) 
  548.             mFreeList.RemoveLast(); 
  549.         else 
  550.             sample = new Sample();
  551.             
  552.         // Maintain our list of samples
  553.         sample -> mNext = NULL;
  554.         if ( mRecentSample ) 
  555.             mRecentSample -> mNext = sample;
  556.         else 
  557.             mSamples = sample;
  558.             
  559.         // Set the sample's data
  560.         sample -> Assign( inCurTime, inSpectrum, mRecentSample, mWave -> mFalloff );
  561.         
  562.         // Update "current" sample shortcuts
  563.         mRecentSample = sample;        
  564.         mLastSampleTime = inCurTime;
  565.     }
  566. }
  567.  
  568.  
  569.  
  570.  
  571. void WhiteCapWorld::discardExpiredRows( long inCurTime ) {
  572.     long dur = mWave -> mSampleDuration;
  573.     Sample* sample = mSamples;
  574.     
  575.     while ( sample ) {
  576.         
  577.         // Step from old to newer samples, discarding until we don't have old samples
  578.         if ( sample -> TimeOfSample() + dur < inCurTime ) {
  579.             if ( sample == mRecentSample )
  580.                 mRecentSample = NULL;
  581.             mFreeList.Add( sample );
  582.             sample = sample -> mNext;
  583.             mSamples = sample; }
  584.         else
  585.             sample = NULL;
  586.     }
  587. }
  588.  
  589.  
  590.  
  591.  
  592.  
  593.  
  594.  
  595. void WhiteCapWorld::ExpireSamples() {
  596.     Sample* sample = mSamples;
  597.  
  598.     while ( sample ) {
  599.         mFreeList.Add( sample );
  600.         sample = sample -> mNext;
  601.     }
  602.  
  603.     mSamples        = NULL;
  604.     mRecentSample    = NULL;
  605. }
  606.  
  607.     
  608.  
  609.  
  610.  
  611.